/*******************************************************************************************
This file is part of iToday.

iToday is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

iToday is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with iToday.  If not, see <http://www.gnu.org/licenses/>.
* ------------------------------------------------------------------------------
*    PoomUtility.cpp - Functions of processing data in poom
* ------------------------------------------------------------------------------
*    Revision History
*    Date                  Author         Activity ID               Activity Headline
*    2009-10-28          Congqin				none				processing functions
*******************************************************************************************/

#include "stdafx.h"

#include <initguid.h>   // For COM INIT_GUID defns
#include <pimstore.h>   // POOM header file

#pragma comment(lib, "pimstore.lib")


IPOutlookApp2 *             g_pOutlookApp = NULL;
IFolder *                   g_pCurrentFolder = NULL;
IPOutlookItemCollection *   g_pOutlookItemCollection = NULL;
const TCHAR *               g_tszCategory = NULL;
UINT                        g_nBitmapHeight;
UINT                        g_nBitmapWidth;


HRESULT InitPoom()
{
    HWND      hWnd     = 0;
    HRESULT   hr       = 0;
    IFolder   *pFolder = NULL;
    IItem     *pItem   = NULL;
    CEPROPVAL propval  = {0};

    if (g_pOutlookApp == NULL)
    {
        hr = CoCreateInstance(CLSID_Application,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IPOutlookApp2,
                              (LPVOID*) &g_pOutlookApp);
        CHR(hr);

        hWnd = FindWindow (SZ_APP_NAME, NULL);
        hr = g_pOutlookApp->Logon((long)hWnd);
        CHR(hr);

        // register for updates

        // Get the folder for contacts.
        hr = g_pOutlookApp->GetDefaultFolder(olFolderContacts, &pFolder);
        CHR(hr);

        // Get the IItem interface for the IFolder.
        hr = pFolder->QueryInterface(IID_IItem, (LPVOID*)&pItem);
        CHR(hr);

        // Set the folder's properties.
        propval.propid    = PIMPR_FOLDERNOTIFICATIONS;
        propval.val.ulVal = PIMFOLDERNOTIFICATION_ALL;
        hr                = pItem->SetProps(0, 1, &propval);

        CHR(hr);
    }

    hr = S_OK;

Error:
    RELEASE_OBJ(pItem);
    RELEASE_OBJ(pFolder);
    if (FAILED(hr))
    {
        // If we failed to log on, don't keep the object around
        RELEASE_OBJ(g_pOutlookApp);
    }
    return hr;
}

HRESULT PoomPopulate( void (*adder)(ContactDataItem*,HANDLE),HANDLE handle)
{
    HRESULT hr = S_OK;
    BSTR bstrPrimary = NULL;
    BSTR bstrCategories = NULL;

    // This will hold our "next" list item, which we'll later
    // pass to this->_addListItem
    ContactDataItem data = {0};
    data.iGroup = 0;

    hr = InitPoom();
    CHR(hr);

    // Get the contacts folder.
    hr = g_pOutlookApp->GetDefaultFolder(olFolderContacts, &g_pCurrentFolder);
    CHR(hr);

    // Get the contacts Items collection.
    hr = g_pCurrentFolder->get_Items(&g_pOutlookItemCollection);
    CHR(hr);

    IContact * pContact = NULL;

    int cItems;
    g_pOutlookItemCollection->get_Count(&cItems);

    for (int i = 0; i < cItems; i++)
    {
        // the itemCollection is indexed 1-based, weird...
        hr = g_pOutlookItemCollection->Item(i+1, (IDispatch**)&pContact);
        if (FAILED(hr))
            continue;

        // grab properties
        hr = pContact->get_Oid(&data.oId);
        CHR(hr);

        hr = pContact->get_FileAs(&bstrPrimary);
        CHR(hr);
        StringCchCopy(data.szPrimaryText, PRIMARY_TEXT_LENGTH, bstrPrimary);
        SysFreeString(bstrPrimary);

        hr = pContact->get_Categories(&bstrCategories);
        CHR(hr);
        StringCchCopy(data.szCategoriesText, SECONDARY_TEXT_LENGTH, bstrCategories);
        SysFreeString(bstrCategories);

        data.iGroup = (int)_totupper(data.szPrimaryText[0]);

        adder(&data,handle);

        // clean up
        RELEASE_OBJ(pContact);
    }

    hr = S_OK;

Error:
    SysFreeString(bstrPrimary);
    SysFreeString(bstrCategories);
    RELEASE_OBJ(pContact);
    return hr;
}

HRESULT PoomCategoriesPopulate( std::vector<ContactCategoryData>  &vContactListData )
{
    HRESULT         hr = E_FAIL;
    IFolder	*		pFolder = NULL;
    IItem *			pFolderIItem = NULL;
    CEPROPVAL *		pVals = NULL;
    ULONG			cbBuffer = 0;

    CEPROPID rgPropID = PIMPR_FOLDER_CATEGORIES;

    InitPoom();
    HANDLE hHeap = GetProcessHeap();

    // Get the IFolder object (Contacts, Contacts, Tasks).
    hr = g_pOutlookApp->GetDefaultFolder(olFolderContacts, &pFolder);
    CHR(hr);

    // Get the IItem object representing a IFolder object.
    hr = pFolder->QueryInterface(__uuidof(IItem), (LPVOID*)&pFolderIItem);
    CHR(hr);

    // Get the list of categories.
    hr = pFolderIItem->GetProps(&rgPropID, CEDB_ALLOWREALLOC, 1, &pVals, &cbBuffer, hHeap);
    CHR(hr);

    // Copy the list of categories for use outside of this function.
    TCHAR * start = pVals->val.lpwstr;
    TCHAR * end = start + _tcslen(pVals->val.lpwstr);
    TCHAR * comma;
    ContactCategoryData  Temp;
    _tcscpy( Temp.m_szCurrentCategoryName ,TEXT("All Contact"));
    vContactListData.push_back (Temp);

    while (start < end)
    {
        comma = _tcschr(start, ',');
        if (comma == NULL)
            comma = end;

        StringCchCopyN( Temp.m_szCurrentCategoryName , SECONDARY_TEXT_LENGTH, start, comma - start);
        vContactListData.push_back (Temp);
        //Logger::Instance().Log( LOG_TRACE, L"Temp.m_szCurrentCategoryName:%s\n",Temp.m_szCurrentCategoryName );

        start = comma + 2;
    }

Error:
    // Free resources.
    HeapFree(hHeap, 0, pVals);
    RELEASE_OBJ(pFolderIItem);
    RELEASE_OBJ(pFolder);

    return  0;
}

bool IsFileExists(const TCHAR * szFilename)
{
    // test if file exists
    HANDLE h = CreateFile(szFilename, GENERIC_READ,
                          FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, NULL, NULL);
    bool exists = h != INVALID_HANDLE_VALUE;
    if (exists)
        CloseHandle(h);
    return exists;
}


bool GetIDialerFilename(TCHAR * szFilename)
{

    HKEY hkey;

    // Where app install data is stored
    LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                               TEXT("Software\\Apps\\Supware.net iDialer"), 0,
                               KEY_QUERY_VALUE, &hkey);

    // Try to find iDialer from installation in registry
    if (0 == result)
    {
        DWORD buffersize = MAX_PATH;
        RegQueryValueEx(hkey, TEXT("InstallDir"), NULL, NULL,
                        (PBYTE)szFilename, &buffersize);
        RegCloseKey(hkey);
    }

    // Otherwise, assume it's stored in the same location
    // (either both in memory or both on storage card)
    else
    {
        // generate path name for IContact
        ::GetModuleFileName(NULL, szFilename, MAX_PATH);
        TCHAR * pstr = _tcsrchr(szFilename, '\\');
        if (pstr) *(pstr) = '\0';

        // Go "up 1" directory. We should then be in \Program Files
        pstr = _tcsrchr(szFilename, '\\');
        if (pstr) *(++pstr) = '\0';

        // Concatenate iDialer program directory
        StringCchCat(szFilename, MAX_PATH, TEXT("iDialer"));
    }

    // Concatenate iDialer exe path
    StringCchCat(szFilename, MAX_PATH, TEXT("\\iDialer.exe"));

    return IsFileExists(szFilename);
}


void Call(TCHAR * number, TCHAR * name)
{
    TCHAR szFilename[MAX_PATH];
    PROCESS_INFORMATION pi;
    TCHAR szArguments[MAX_PATH];

    HINSTANCE hiCellCoreDll;
    TAPIREQUESTMAKECALL tapiRequestMakeCall;

    if (GetIDialerFilename(szFilename))
    {
        StringCchPrintf(szArguments, MAX_PATH, TEXT("%s -name=%s"), number, name);
        CreateProcess(szFilename, szArguments,
                      NULL, NULL, FALSE, NULL, NULL, NULL, NULL, &pi);
    }
    else
    {
        hiCellCoreDll = LoadLibrary(TEXT("cellcore.dll"));
        if (!hiCellCoreDll)
        {
            // TODO: alert user?
            return;
        }

        tapiRequestMakeCall = (TAPIREQUESTMAKECALL)GetProcAddress(
                                  hiCellCoreDll, TEXT("tapiRequestMakeCallW"));

        tapiRequestMakeCall(number, NULL, name, NULL);
    }
}


HRESULT ProcessPoomClick( ContactDataItem * data , ContactButton eParam )
{
    HRESULT hr = S_OK;
    IDispatch * pDisp = NULL;
    IItem * pItem = NULL;
    IContact * pContact = NULL;
    BSTR buffer = NULL;
    HWND hWnd = 0;

    TCHAR szPhoneNumber[15] ={0};
    TCHAR szObjectPath[64] = {0};
    TCHAR szArguments[64] = {0};
    TCHAR szIconPath[MAX_PATH] = {0};

    int oid = data->oId;
    if (oid == -1)
        return E_INVALIDARG;

    hr = InitPoom();
    CHR(hr);

    hr = g_pOutlookApp->GetItemFromOid(oid, &pDisp);
    CHR(hr);

    switch ( eParam )
    {
    case EditButton:
        hr = pDisp->QueryInterface(IID_IItem, (LPVOID*)&pItem);
        CHR(hr);
        hWnd = FindWindow (SZ_APP_NAME, NULL);
        hr = pItem->Edit(hWnd);
        break;

    case DetailsButton:
        hr = pDisp->QueryInterface(IID_IItem, (LPVOID*)&pItem);
        CHR(hr);
        hWnd = FindWindow (SZ_APP_NAME, NULL);
        hr = pItem->Display(hWnd);
        CHR(hr);
        break;
    case DailPhoneButton:

        ((IContact *)pDisp)->get_MobileTelephoneNumber(&buffer);
        StringCchCopy( szPhoneNumber, 15, buffer);
        SysFreeString(buffer);
        if (_tcslen(szPhoneNumber))
        {
            hr = pDisp->QueryInterface(IID_IContact, (LPVOID*)&pContact);
            CHR(hr);
            pContact->get_FileAs(&buffer);

            //if (x > 0.8)
            //    SendSMS(data->szPrimaryText, buffer);
            //else
            Call(szPhoneNumber, buffer);

            SysFreeString(buffer);
        }
        else
        {
            HWND hWnd = FindWindow (SZ_APP_NAME, NULL);
            MessageBox( hWnd, L"The Number is NULL",NULL,MB_OK );
        }
        break;

    default:
        break;
    }

    hr = S_OK;

Error:
    RELEASE_OBJ(pItem);
    RELEASE_OBJ(pContact);
    RELEASE_OBJ(pDisp);
    return hr;
}


HRESULT PoomGetTitle(ContactDataItem * parent, TCHAR * buffer, int cchDest )
{

    StringCchCopy(buffer, cchDest, parent->szPrimaryText);
    return S_OK;
}

HRESULT PoomGetGroup(ContactDataItem * data, TCHAR * buffer, int cchDest )
{

    buffer[0] = (TCHAR)data->iGroup;
    buffer[1] = 0;
    return S_OK;
}

HRESULT PoomAddItem()
{
    IDispatch * pDisp = NULL;
    IItem * pItem = NULL;
    HRESULT hr = S_OK;
    HWND hWnd;

    hr = InitPoom();
    CHR(hr);

    hr = g_pOutlookApp->CreateItem(olContactItem, (IDispatch**)&pDisp);
    CHR(hr);

    hr = pDisp->QueryInterface(IID_IItem, (LPVOID*)&pItem);
    CHR(hr);

    hWnd = FindWindow (SZ_APP_NAME, NULL);
    hr = pItem->Edit(hWnd);

Error:
    RELEASE_OBJ(pItem);
    RELEASE_OBJ(pDisp);
    return hr;
}

